using System;
using System.Diagnostics;
using System.Windows.Forms;
using GTA;
using GTA.Math;
using GTA.Native;
using NativeUI;
using MainMenu = CustomPeds.Menus.MainMenu;

namespace CustomPeds;

public class Main : Script
{
	public enum MaleStatus
	{
		None,
		OnFoot,
		Vehicle
	}

	public enum FemaleStatus
	{
		None,
		Accompany
	}

	public enum Member
	{
		P1,
		P2,
		P3,
		P4,
		Clone
	}

	public static MenuPool pool = new MenuPool();

	public static MaleStatus m_Status;

	public static FemaleStatus f_Status;

	public static Origin P1 = new Origin();

	public static Origin P2 = new Origin();

	public static Origin P3 = new Origin();

	public static Origin Clone = new Origin();

	public static int vindex = 0;

	// 优化：使用静态数组避免重复分配
	private static Vehicle[] vehicle = new Vehicle[0];
	private static DateTime lastVehicleCheck = DateTime.MinValue;
	private static readonly TimeSpan vehicleCheckInterval = TimeSpan.FromSeconds(5);

	// 进入车辆日志状态：用于仅在本次上车时记录一次
	private static bool wasBothInVehicle;

	// 菜单状态跟踪 - 实现开关功能
	public static bool isMainMenuVisible;
	
	// 菜单处理：在菜单打开时每帧处理，避免闪烁

	// 开关键处理：仅在按下瞬间触发一次，抬起后才允许再次触发
	private static bool isStartKeyDown;

	// 当主菜单被代码隐藏时调用：同步可见状态并重置按键闸门
	public static void OnMainMenuHidden()
	{
		isMainMenuVisible = false;
		isStartKeyDown = false;
	}

	private static string ResolveSeatName(Vehicle vehicle, Ped ped)
	{
		if (vehicle == null || ped == null)
		{
			return "Unknown";
		}
		try
		{
			// 先判断是否为驾驶位
			if (vehicle.Driver != null && vehicle.Driver.Exists() && vehicle.Driver.Handle == ped.Handle)
			{
				return "Driver";
			}
			// 遍历乘客座
			int passengerSeats = vehicle.PassengerSeats;
			for (int i = 0; i < passengerSeats; i++)
			{
				var seatPed = vehicle.GetPedOnSeat((VehicleSeat)i);
				if (seatPed != null && seatPed.Exists() && seatPed.Handle == ped.Handle)
				{
					return i == 0 ? "Passenger" : $"Passenger{i}";
				}
			}
		}
		catch
		{
			// 忽略异常，返回未知
		}
		return "Unknown";
	}

	public static bool IsPedDriverOfCurrentVehicle(Ped ped)
	{
		try
		{
			if (ped == null || !ped.IsInVehicle())
			{
				return false;
			}
			var v = ped.CurrentVehicle;
			return v != null && v.Exists() && v.Driver != null && v.Driver.Exists() && v.Driver.Handle == ped.Handle;
		}
		catch
		{
			return false;
		}
	}

	public static bool IsPedInSeat(Vehicle vehicle, Ped ped, VehicleSeat seat)
	{
		try
		{
			if (vehicle == null || ped == null || !vehicle.Exists() || !ped.Exists())
			{
				return false;
			}
			if (seat == VehicleSeat.Driver)
			{
				return vehicle.Driver != null && vehicle.Driver.Exists() && vehicle.Driver.Handle == ped.Handle;
			}
			var occ = vehicle.GetPedOnSeat(seat);
			return occ != null && occ.Exists() && occ.Handle == ped.Handle;
		}
		catch
		{
			return false;
		}
	}

	public static bool IsSeatFree(Vehicle vehicle, VehicleSeat seat)
	{
		try
		{
			if (vehicle == null || !vehicle.Exists())
			{
				return false;
			}
			if (seat == VehicleSeat.Driver)
			{
				return vehicle.Driver == null || !vehicle.Driver.Exists() || vehicle.Driver.Handle == 0;
			}
			var occ = vehicle.GetPedOnSeat(seat);
			return occ == null || !occ.Exists() || occ.Handle == 0;
		}
		catch
		{
			return false;
		}
	}

	public static bool TryGetActualSeat(Vehicle vehicle, Ped ped, out VehicleSeat seat)
	{
		seat = VehicleSeat.Any;
		try
		{
			if (vehicle == null || ped == null || !vehicle.Exists() || !ped.Exists())
			{
				return false;
			}
			if (vehicle.Driver != null && vehicle.Driver.Exists() && vehicle.Driver.Handle == ped.Handle)
			{
				seat = VehicleSeat.Driver;
				return true;
			}
			int passengerSeats = vehicle.PassengerSeats;
			for (int i = 0; i < passengerSeats; i++)
			{
				var occ = vehicle.GetPedOnSeat((VehicleSeat)i);
				if (occ != null && occ.Exists() && occ.Handle == ped.Handle)
				{
					seat = (VehicleSeat)i;
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private static VehicleSeat GetFirstAvailablePassengerSeat(Vehicle vehicle)
	{
		if (vehicle == null || !vehicle.Exists())
		{
			return VehicleSeat.Any;
		}
		int passengerSeats = vehicle.PassengerSeats;
		for (int i = 0; i < passengerSeats; i++)
		{
			var seat = (VehicleSeat)i;
			if (IsSeatFree(vehicle, seat))
			{
				return seat;
			}
		}
		return VehicleSeat.Any;
	}

	public static bool EnsureDriverAndPassenger(Vehicle vehicle, Ped driverPed, Ped passengerPed, int timeoutMs = 8000)
	{
		try
		{
			if (vehicle == null || !vehicle.Exists())
			{
				return false;
			}
			// 先确保驾驶位归属
			if (!IsPedDriverOfCurrentVehicle(driverPed))
			{
				// 如果其他人占据驾驶位且不是目标驾驶员（常见为另一位角色），让其下车
				if (vehicle.Driver != null && vehicle.Driver.Exists() && driverPed != null && vehicle.Driver.Handle != driverPed.Handle)
				{
					vehicle.Driver.Task.LeaveVehicle();
					Wait(500);
				}
				// 指令目标驾驶员进入驾驶位
				driverPed?.Task.EnterVehicle(vehicle, VehicleSeat.Driver, 1500, 2f, 16);
			}
			// 等待驾驶员就位
			var start = DateTime.Now;
			while (!IsPedDriverOfCurrentVehicle(driverPed))
			{
				if ((DateTime.Now - start).TotalMilliseconds > timeoutMs)
				{
					break;
				}
				Wait(100);
			}

			// 为乘客选择第一个可用乘客座
			var passengerSeat = GetFirstAvailablePassengerSeat(vehicle);
			if (passengerPed != null && passengerSeat != VehicleSeat.Any && !IsPedInSeat(vehicle, passengerPed, passengerSeat))
			{
				passengerPed.Task.EnterVehicle(vehicle, passengerSeat, 1500, 2f, 16);
				var pStart = DateTime.Now;
				while (!IsPedInSeat(vehicle, passengerPed, passengerSeat))
				{
					if ((DateTime.Now - pStart).TotalMilliseconds > timeoutMs)
					{
						break;
					}
					Wait(100);
				}
			}
			return IsPedDriverOfCurrentVehicle(driverPed);
		}
		catch
		{
			return false;
		}
	}

	public Main()
	{
		KeyDown += OnKeyDown;
		KeyUp += OnKeyUp;
		Tick += OnTick;
		// 菜单需要每帧处理，设置为每帧Tick
		Interval = 0;
		
		// 初始化日志系统
		LogHelper.InitializeLog();
		LogHelper.WriteInfo("CustomPeds脚本已启动");
	}

	private void OnTick(object sender, EventArgs e)
	{
		try
		{
			// 执行车辆修复功能
			FadeOutVehDisappearRepair();
			
			// 当主角和女友均在车内且从“未同时在车内”切换到“同时在车内”时，记录一次座位信息
			bool p1InVehicle = P1.Character != null && P1.Character.IsInVehicle();
			bool p2InVehicle = P2.Character != null && P2.Character.IsInVehicle();
			bool sameVehicle = false;
			if (p1InVehicle && p2InVehicle)
			{
				var v1 = P1.Character.CurrentVehicle;
				var v2 = P2.Character.CurrentVehicle;
				sameVehicle = (v1 != null && v2 != null && v1.Exists() && v2.Exists() && v1.Handle == v2.Handle);
			}
			if (p1InVehicle && p2InVehicle && sameVehicle)
			{
				if (!wasBothInVehicle)
				{
					var vehicle = P1.Character.CurrentVehicle;
					string p1SeatName = ResolveSeatName(vehicle, P1.Character);
					string p2SeatName = ResolveSeatName(vehicle, P2.Character);
					LogHelper.WriteInfo($"进入车里，主角座位：{p1SeatName}，女友座位：{p2SeatName}");
				}
				wasBothInVehicle = true;
			}
			else
			{
				wasBothInVehicle = false;
			}
			
			// 仅在菜单打开时处理，避免无菜单时不必要的处理
			if (pool.IsAnyMenuOpen())
			{
				pool.ProcessMenus();
			}
		}
		catch (Exception ex)
		{
			// 添加异常处理，防止脚本崩溃
			try
			{
				// 尝试使用安全的通知方式
				SafeNotify($"脚本错误: {ex.Message}");
			}
			catch
			{
				// 如果连安全通知都失败，记录到日志
				Debug.WriteLine($"Main脚本错误: {ex.Message}");
			}
		}
	}
	
	private static void SafeNotify(string message)
	{
		try
		{
			// 尝试使用UI.Notify，如果失败则使用其他方式
			UI.Notify(message);
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex,"SafeNotify - 提示");
			try
			{
				// 备用方案：使用游戏内聊天
				Game.Player.Character.PlayAmbientSpeech1("GENERIC_HI", immediately: true);
			}
			catch
			{
				// 最后的备用方案：记录到调试输出
				Debug.WriteLine($"通知失败: {message}");
			}
		}
	}

	public static void FadeOutVehDisappearRepair()
	{
		// 优化：减少频繁的车辆检查
		if (DateTime.Now.Subtract(lastVehicleCheck) < vehicleCheckInterval)
		{
			return;
		}
		
		lastVehicleCheck = DateTime.Now;
		
		if (Game.IsScreenFadedOut && vehicle.Length == 0)
		{
			try
			{
				vehicle = World.GetNearbyVehicles(Game.Player.Character.Position, 100f);
				for (int i = 0; i < vehicle.Length; i++)
				{
					if (vehicle[i] != null && vehicle[i].Exists())
					{
						vehicle[i].IsPersistent = true;
					}
				}
			}
			catch (Exception ex)
			{
				LogHelper.WriteException(ex, "FadeOutVehDisappearRepair - 获取附近车辆");
				vehicle = new Vehicle[0];
			}
		}
		vehicle = new Vehicle[0];
	}

	private void OnKeyDown(object sender, KeyEventArgs e)
	{
		// 处理菜单开关逻辑
		if (e.KeyCode == ScriptSettings.startKey)
		{
			try
			{
				// 仅在按下的首个 KeyDown 时触发，避免长按/连发导致的多次切换
				if (isStartKeyDown)
				{
					return;
				}
				isStartKeyDown = true;

				if (!isMainMenuVisible)
				{
					// 第一次点击：显示菜单并保持显示
					InitMale();
					if (m_Status == MaleStatus.None && IsGirlfriendInNear(3f))
					{
						MainMenu.menu.MenuItems[2].Enabled = true;
					}
					else
					{
						MainMenu.menu.MenuItems[2].Enabled = false;
					}
					MainMenu.menu.Visible = true;
					MainMenu.menu.RefreshIndex();
					isMainMenuVisible = true;
					
					LogHelper.WriteInfo($"主菜单已打开并保持显示 (按键: {ScriptSettings.startKey})");
				}
				else
				{
					// 再次点击：隐藏菜单
					MainMenu.menu.Visible = false;
					isMainMenuVisible = false;
					
					LogHelper.WriteInfo($"主菜单已关闭 (按键: {ScriptSettings.startKey})");
				}
			}
			catch (Exception ex)
			{
				SafeNotify($"菜单操作错误: {ex.Message}");
				LogHelper.WriteException(ex, "OnKeyDown - 菜单开关操作");
			}
		}
	}

	private void OnKeyUp(object sender, KeyEventArgs e)
	{
		if (e.KeyCode == ScriptSettings.startKey)
		{
			// 按键抬起后恢复允许再次触发
			isStartKeyDown = false;
		}
	}



	public static void InitMale()
	{
		if (P1.Character == null)
		{
			P1.Character = Game.Player.Character;
			P1.Character.CanWearHelmet = P1.CanWearHelmet;
			P1.Character.DrivingStyle = P1.drivingStyle;
			P1.BuildPedData(P1.Character, Member.P1, isAddonPed: false);
		}
	}

	public static void InitFemale()
	{
		if (P2.Character != null)
		{
			return;
		}
		
		try
		{
			P2.Character = CreatePed(PedHash.AmandaTownley);
			if (P2.Character != null)
			{
				P2.Character.Task.LookAt(P1.Character);
				P2.Character.BlockPermanentEvents = true;
				P2.Character.IsPersistent = true;
				P2.Character.CanWearHelmet = P2.CanWearHelmet;
				if (P2.Follow)
				{
					P1.Character.CurrentPedGroup.Add(P2.Character, leader: false);
				}
				P2.Character.IsInvincible = P2.Invincible;
				P2.Character.DrivingStyle = P2.drivingStyle;
				P2.BuildPedData(P2.Character, Member.P2, isAddonPed: false);
				P2.skin.SetWeapons(P1.skin.GetWeaponsData());
				f_Status = FemaleStatus.Accompany;
			}
		}
		catch (Exception ex)
		{
			SafeNotify($"创建女友失败: {ex.Message}");
		}
	}

	public static bool IsGirlfriendInNear(float radius)
	{
		if (P2.Character == null)
		{
			return false;
		}
		
		try
		{
			Ped[] nearbyPeds = World.GetNearbyPeds(P1.Character, radius);
			for (int i = 0; i < nearbyPeds.Length; i++)
			{
				if (nearbyPeds[i] != null && nearbyPeds[i].Handle == P2.Character.Handle)
				{
					return true;
				}
			}
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "IsGirlfriendInNear - 获取附近Ped");
		}
		return false;
	}

	public static void ReBuildP2(Ped ped, string modelName, bool isAddonPed = false)
	{
		try
		{
			if (Game.Player.Character.CurrentPedGroup.Contains(ped))
			{
				ped.LeaveGroup();
			}
			if (ped != null)
			{
				ped.MarkAsNoLongerNeeded();
				ped.Delete();
			}
			ped = CreatePed(modelName, isAddonPed);
			if (ped == null)
			{
				ped = CreatePed(PedHash.AmandaTownley);
				isAddonPed = false;
			}
			P2.Character = ped;
			P2.Character.BlockPermanentEvents = true;
			P2.Character.IsPersistent = true;
			P2.Character.SetDefaultClothes();
			P2.BuildPedData(P2.Character, Member.P2, isAddonPed);
			f_Status = FemaleStatus.Accompany;
		}
		catch (Exception ex)
		{
			SafeNotify($"重建女友失败: {ex.Message}");
		}
	}

	public static void ReBuildClone(Ped ped, string modelName, bool isAddonPed = false)
	{
		try
		{
			if (ped != null)
			{
				ped.MarkAsNoLongerNeeded();
				ped.Delete();
			}
			ped = CreatePed(modelName, isAddonPed);
			if (ped == null)
			{
				ped = CreatePed(PedHash.Franklin);
			}
			Clone.Character = ped;
			Clone.Character.BlockPermanentEvents = true;
			Clone.Character.IsPersistent = true;
			Clone.Character.SetDefaultClothes();
			Clone.skin = new Skin(ped, isAddonPed);
		}
		catch (Exception ex)
		{
			SafeNotify($"重建克隆失败: {ex.Message}");
		}
	}

	public static bool ChangePlayerModel(string pedName, bool isAddonPed = false)
	{
		bool flag = true;
		Model model = null;
		
		try
		{
			model = (!isAddonPed) ? new Model((PedHash)Enum.Parse(typeof(PedHash), pedName)) : new Model(pedName);
			bool flag2 = model.Request(5000);
			if (model.IsInCdImage && model.IsValid && flag2)
			{
				Ped ped = World.CreatePed(model, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0f, -20f, -1f)), Game.Player.Character.Heading - 180f);
				ped.IsVisible = false;
				Wait(500);
				if (ped.GetBoneIndex(Bone.RB_L_ArmRoll) == -1 && !isAddonPed)
				{
					flag = false;
				}
				ped.MarkAsNoLongerNeeded();
				ped.Delete();
				if (flag)
				{
					Function.Call(Hash._0x00A1CADD00108836, Game.Player, model.Hash);
				}
			}
			else
			{
				flag = false;
			}
		}
		catch (Exception ex)
		{
			flag = false;
			SafeNotify($"更换模型失败: {ex.Message}");
		}
		finally
		{
			// 确保Model被正确释放
			if (model != null)
			{
				model.MarkAsNoLongerNeeded();
			}
		}
		
		return flag;
	}

	public static Ped CreatePed(string pedName, bool isAddonPed = false)
	{
		Ped ped = null;
		Model model = null;
		
		try
		{
			model = (!isAddonPed) ? new Model((PedHash)Enum.Parse(typeof(PedHash), pedName)) : new Model(pedName);
			bool flag = model.Request(5000);
			if (model.IsInCdImage && model.IsValid && flag)
			{
				ped = World.CreatePed(model, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0f, 2f, -1f)), Game.Player.Character.Heading - 180f);
				ped.IsVisible = false;
				Wait(500);
				if (ped.GetBoneIndex(Bone.RB_L_ArmRoll) == -1 && !isAddonPed)
				{
					ped.MarkAsNoLongerNeeded();
					ped.Delete();
					ped = null;
				}
			}
			if (ped != null)
			{
				ped.IsVisible = true;
			}
		}
		catch (Exception ex)
		{
			SafeNotify($"创建Ped失败: {ex.Message}");
		}
		finally
		{
			// 确保Model被正确释放
			if (model != null)
			{
				model.MarkAsNoLongerNeeded();
			}
		}
		
		return ped;
	}

	public static Ped CreatePed(PedHash pedHash)
	{
		Ped ped = null;
		Model model = null;
		
		try
		{
			model = new Model(pedHash);
			bool flag = model.Request(5000);
			if (model.IsInCdImage && model.IsValid && flag)
			{
				ped = World.CreatePed(model, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0f, 2f, -0.5f)), Game.Player.Character.Heading - 180f);
				ped.IsVisible = false;
				Wait(500);
				if (ped.GetBoneIndex(Bone.RB_L_ArmRoll) == -1)
				{
					ped.MarkAsNoLongerNeeded();
					ped.Delete();
					ped = null;
				}
			}
			if (ped != null)
			{
				ped.IsVisible = true;
			}
			else
			{
				ped = CreatePed(PedHash.AmandaTownley);
			}
		}
		catch (Exception ex)
		{
			SafeNotify($"创建Ped失败: {ex.Message}");
		}
		finally
		{
			// 确保Model被正确释放
			if (model != null)
			{
				model.MarkAsNoLongerNeeded();
			}
		}
		
		return ped;
	}
}
